using Exception = System.Exception;

namespace Pngcs.Chunks
{
	/// <summary> bKGD chunk, see http://www.w3.org/TR/PNG/#11bKGD </summary>
	public class PngChunkBKGD : PngChunkSingle
	{

		public const string ID = ChunkHelper.bKGD;
		
		// this chunk structure depends on the image type
		// only one of these is meaningful
		int gray;
		int red, green, blue;
		int paletteIndex;

		public PngChunkBKGD ( ImageInfo info )
			: base( ID , info )
		{

		}

		public override ChunkOrderingConstraint GetOrderingConstraint () => ChunkOrderingConstraint.AFTER_PLTE_BEFORE_IDAT;

		public override ChunkRaw CreateRawChunk ()
		{
			ChunkRaw chunk = null;
			byte[] data = chunk.Data;
			if( ImgInfo.Greyscale )
			{
				chunk = CreateEmptyChunk( 2 , true );
				PngHelperInternal.WriteInt2tobytes( gray , data , 0 );
			}
			else if( ImgInfo.Indexed )
			{
				chunk = CreateEmptyChunk( 1 , true );
				data[0] = (byte)paletteIndex;
			}
			else
			{
				chunk = CreateEmptyChunk( 6 , true );
				PngHelperInternal.WriteInt2tobytes( red , data , 0 );
				PngHelperInternal.WriteInt2tobytes( green , data , 0 );
				PngHelperInternal.WriteInt2tobytes( blue , data , 0 );
			}
			return chunk;
		}

		public override void ParseFromRaw ( ChunkRaw chunk )
		{
			byte[] data = chunk.Data;
			if( ImgInfo.Greyscale )
			{
				gray = PngHelperInternal.ReadInt2fromBytes( data , 0 );
			}
			else if( ImgInfo.Indexed )
			{
				paletteIndex = (int)(data[0] & 0xff);
			}
			else
			{
				red = PngHelperInternal.ReadInt2fromBytes( data , 0 );
				green = PngHelperInternal.ReadInt2fromBytes( data , 2 );
				blue = PngHelperInternal.ReadInt2fromBytes( data , 4 );
			}
		}

		public override void CloneDataFromRead ( PngChunk other )
		{
			PngChunkBKGD otherx = (PngChunkBKGD)other;
			gray = otherx.gray;
			red = otherx.red;
			green = otherx.red;
			blue = otherx.red;
			paletteIndex = otherx.paletteIndex;
		}

		/// <summary> Set gray value (0-255 if bitdept=8) </summary>
		public void SetGray ( int gray )
		{
			if( !ImgInfo.Greyscale ) throw new Exception("only gray images support this");
			this.gray = gray;
		}

		/// <summary> Gets gray value  </summary>
		/// <returns>gray value  (0-255 if bitdept=8)</returns>
		public int GetGray ()
		{
			if( !ImgInfo.Greyscale ) throw new Exception("only gray images support this");
			return gray;
		}

		/// <summary> Set pallette index - only for indexed </summary>
		public void SetPaletteIndex ( int index )
		{
			if( !ImgInfo.Indexed ) throw new Exception("only indexed (pallete) images support this");
			this.paletteIndex = index;
		}

		/// <summary> Get pallette index - only for indexed </summary>
		public int GetPaletteIndex ()
		{
			if( !ImgInfo.Indexed ) throw new Exception("only indexed (pallete) images support this");
			return paletteIndex;
		}

		/// <summary> Sets rgb value, only for rgb images </summary>
		public void SetRGB ( int r , int g , int b )
		{
			if( ImgInfo.Greyscale || ImgInfo.Indexed ) throw new Exception("only rgb or rgba images support this");
			red = r;
			green = g;
			blue = b;
		}

		/// <summary> Gets rgb value, only for rgb images </summary>
		/// <returns> [r,g,b] array </returns>
		public int[] GetRGB ()
		{
			if( ImgInfo.Greyscale || ImgInfo.Indexed ) throw new Exception("only rgb or rgba images support this");
			return new int[]{ red, green, blue };
		}

	}
}
